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
22 #include "wine/port.h"
28 // for read_directory_unix()
29 #if !defined(_NO_EXTENSIONS)
42 #define _MAX_FNAME 256
43 #define _MAX_DIR _MAX_FNAME
44 #define _MAX_EXT _MAX_FNAME
48 WINEFILE_GLOBALS Globals;
50 extern void WineLicense(HWND hWnd);
51 extern void WineWarranty(HWND hWnd);
53 typedef struct _Entry {
64 #ifndef _NO_EXTENSIONS
65 BY_HANDLE_FILE_INFORMATION bhfi;
74 TCHAR volname[_MAX_FNAME];
84 COL_ATTRIBUTES = 0x08,
87 COL_ALL = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_DOSNAMES
91 COL_ALL = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_DOSNAMES|COL_INDEX|COL_LINKS
104 #ifndef _NO_EXTENSIONS
108 #ifndef _NO_EXTENSIONS
114 int positions[COLUMNS+1];
126 int focus_pane; // 0: left 1: right
129 BOOL header_wdths_ok;
131 TCHAR path[MAX_PATH];
134 SORT_ORDER sortOrder;
138 static void read_directory(Entry* parent, LPCTSTR path, int sortOrder);
139 static void set_curdir(ChildWnd* child, Entry* entry);
141 LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
142 LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
143 LRESULT CALLBACK TreeWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
146 static void display_error(HWND hwnd, DWORD error)
150 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
151 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL))
152 MessageBox(hwnd, msg, _T("Winefile"), MB_OK);
154 MessageBox(hwnd, _T("Error"), _T("Winefile"), MB_OK);
160 static void read_directory_win(Entry* parent, LPCTSTR path)
162 Entry* entry = (Entry*) malloc(sizeof(Entry));
163 int level = parent->level + 1;
166 #ifndef _NO_EXTENSIONS
170 TCHAR buffer[MAX_PATH], *p;
171 for(p=buffer; *path; )
174 lstrcpy(p, _T("\\*"));
176 hFind = FindFirstFile(buffer, &entry->data);
178 if (hFind != INVALID_HANDLE_VALUE) {
179 parent->down = entry;
184 entry->expanded = FALSE;
185 entry->scanned = FALSE;
186 entry->level = level;
188 #ifdef _NO_EXTENSIONS
189 // hide directory entry "."
190 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
191 LPCTSTR name = entry->data.cFileName;
193 if (name[0]=='.' && name[1]=='\0')
197 entry->unix_dir = FALSE;
198 entry->bhfi_valid = FALSE;
200 lstrcpy(p+1, entry->data.cFileName);
202 hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
203 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
205 if (hFile != INVALID_HANDLE_VALUE) {
206 if (GetFileInformationByHandle(hFile, &entry->bhfi))
207 entry->bhfi_valid = TRUE;
215 entry = (Entry*) malloc(sizeof(Entry));
219 } while(FindNextFile(hFind, &entry->data));
229 parent->scanned = TRUE;
233 static Entry* find_entry_win(Entry* parent, LPCTSTR name)
237 for(entry=parent->down; entry; entry=entry->next) {
239 LPCTSTR q = entry->data.cFileName;
242 if (!*p || *p==_T('\\') || *p==_T('/'))
244 } while(tolower(*p++) == tolower(*q++));
247 q = entry->data.cAlternateFileName;
250 if (!*p || *p==_T('\\') || *p==_T('/'))
252 } while(tolower(*p++) == tolower(*q++));
259 static Entry* read_tree_win(Root* root, LPCTSTR path, int sortOrder)
261 TCHAR buffer[MAX_PATH];
262 Entry* entry = &root->entry;
266 #ifndef _NO_EXTENSIONS
267 entry->unix_dir = FALSE;
271 while(*s && *s!=_T('\\') && *s!=_T('/'))
274 while(*s==_T('\\') || *s==_T('/'))
280 read_directory(entry, buffer, sortOrder);
283 entry->expanded = TRUE;
288 entry = find_entry_win(entry, s);
295 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
297 BOOL to_filetime(const time_t* t, FILETIME* ftime)
299 struct tm* tm = gmtime(t);
305 stime.wYear = tm->tm_year+1900;
306 stime.wMonth = tm->tm_mon+1;
308 stime.wDay = tm->tm_mday;
309 stime.wHour = tm->tm_hour;
310 stime.wMinute = tm->tm_min;
311 stime.wSecond = tm->tm_sec;
313 return SystemTimeToFileTime(&stime, ftime);
316 static void read_directory_unix(Entry* parent, LPCTSTR path)
318 Entry* entry = (Entry*) malloc(sizeof(Entry));
319 int level = parent->level + 1;
322 DIR* dir = opendir(path);
327 TCHAR buffer[MAX_PATH], *p;
329 for(p=buffer; *path; )
332 if (p==buffer || p[-1]!='/')
335 parent->down = entry;
337 while((ent=readdir(dir))) {
338 entry->unix_dir = TRUE;
339 lstrcpy(entry->data.cFileName, ent->d_name);
340 entry->data.dwFileAttributes = ent->d_name[0]=='.'? FILE_ATTRIBUTE_HIDDEN: 0;
342 strcpy(p, ent->d_name);
344 if (!stat(buffer, &st)) {
345 if (S_ISDIR(st.st_mode))
346 entry->data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
348 entry->data.nFileSizeLow = st.st_size & 0xFFFFFFFF;
349 entry->data.nFileSizeHigh = st.st_size >> 32;
351 memset(&entry->data.ftCreationTime, 0, sizeof(FILETIME));
352 to_filetime(&st.st_atime, &entry->data.ftLastAccessTime);
353 to_filetime(&st.st_mtime, &entry->data.ftLastWriteTime);
355 entry->bhfi.nFileIndexLow = ent->d_ino;
356 entry->bhfi.nFileIndexHigh = 0;
358 entry->bhfi.nNumberOfLinks = st.st_nlink;
360 entry->bhfi_valid = TRUE;
362 entry->data.nFileSizeLow = 0;
363 entry->data.nFileSizeHigh = 0;
364 entry->bhfi_valid = FALSE;
369 entry->expanded = FALSE;
370 entry->scanned = FALSE;
371 entry->level = level;
375 entry = (Entry*) malloc(sizeof(Entry));
389 parent->scanned = TRUE;
392 static Entry* find_entry_unix(Entry* parent, LPCTSTR name)
396 for(entry=parent->down; entry; entry=entry->next) {
398 LPCTSTR q = entry->data.cFileName;
401 if (!*p || *p==_T('/'))
403 } while(*p++ == *q++);
409 static Entry* read_tree_unix(Root* root, LPCTSTR path, int sortOrder)
411 TCHAR buffer[MAX_PATH];
412 Entry* entry = &root->entry;
416 entry->unix_dir = TRUE;
419 while(*s && *s!=_T('/'))
428 read_directory(entry, buffer, sortOrder);
431 entry->expanded = TRUE;
436 entry = find_entry_unix(entry, s);
445 // directories first...
446 static int compareType(const WIN32_FIND_DATA* fd1, const WIN32_FIND_DATA* fd2)
448 int dir1 = fd1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
449 int dir2 = fd2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
451 return dir2==dir1? 0: dir2<dir1? -1: 1;
455 static int compareName(const void* arg1, const void* arg2)
457 const WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
458 const WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
460 int cmp = compareType(fd1, fd2);
464 return lstrcmpi(fd1->cFileName, fd2->cFileName);
467 static int compareExt(const void* arg1, const void* arg2)
469 const WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
470 const WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
471 const TCHAR *name1, *name2, *ext1, *ext2;
473 int cmp = compareType(fd1, fd2);
477 name1 = fd1->cFileName;
478 name2 = fd2->cFileName;
480 ext1 = _tcsrchr(name1, _T('.'));
481 ext2 = _tcsrchr(name2, _T('.'));
493 cmp = lstrcmpi(ext1, ext2);
497 return lstrcmpi(name1, name2);
500 static int compareSize(const void* arg1, const void* arg2)
502 WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
503 WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
505 int cmp = compareType(fd1, fd2);
509 cmp = fd2->nFileSizeHigh - fd1->nFileSizeHigh;
516 cmp = fd2->nFileSizeLow - fd1->nFileSizeLow;
518 return cmp<0? -1: cmp>0? 1: 0;
521 static int compareDate(const void* arg1, const void* arg2)
523 WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
524 WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
526 int cmp = compareType(fd1, fd2);
530 return CompareFileTime(&fd2->ftLastWriteTime, &fd1->ftLastWriteTime);
534 static int (*sortFunctions[])(const void* arg1, const void* arg2) = {
535 compareName, // SORT_NAME
536 compareExt, // SORT_EXT
537 compareSize, // SORT_SIZE
538 compareDate // SORT_DATE
542 static void SortDirectory(Entry* parent, SORT_ORDER sortOrder)
544 Entry* entry = parent->down;
549 for(entry=parent->down; entry; entry=entry->next)
553 array = (Entry**) alloca(len*sizeof(Entry*));
556 for(entry=parent->down; entry; entry=entry->next)
559 // call qsort with the appropriate compare function
560 qsort(array, len, sizeof(array[0]), sortFunctions[sortOrder]);
562 parent->down = array[0];
564 for(p=array; --len; p++)
572 static void read_directory(Entry* parent, LPCTSTR path, int sortOrder)
574 TCHAR buffer[MAX_PATH];
579 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
580 if (parent->unix_dir)
582 read_directory_unix(parent, path);
584 if (Globals.prescan_node) {
593 for(entry=parent->down; entry; entry=entry->next)
594 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
595 lstrcpy(d, entry->data.cFileName);
596 read_directory_unix(entry, buffer);
597 SortDirectory(entry, sortOrder);
604 read_directory_win(parent, path);
606 if (Globals.prescan_node) {
615 for(entry=parent->down; entry; entry=entry->next)
616 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
617 lstrcpy(d, entry->data.cFileName);
618 read_directory_win(entry, buffer);
619 SortDirectory(entry, sortOrder);
624 SortDirectory(parent, sortOrder);
628 static ChildWnd* alloc_child_window(LPCTSTR path)
630 TCHAR drv[_MAX_DRIVE+1], dir[_MAX_DIR], name[_MAX_FNAME], ext[_MAX_EXT];
631 ChildWnd* child = (ChildWnd*) malloc(sizeof(ChildWnd));
632 Root* root = &child->root;
635 memset(child, 0, sizeof(ChildWnd));
637 child->left.treePane = TRUE;
638 child->left.visible_cols = 0;
640 child->right.treePane = FALSE;
641 #ifndef _NO_EXTENSIONS
642 child->right.visible_cols = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS;
644 child->right.visible_cols = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES;
647 child->pos.length = sizeof(WINDOWPLACEMENT);
648 child->pos.flags = 0;
649 child->pos.showCmd = SW_SHOWNORMAL;
650 child->pos.rcNormalPosition.left = CW_USEDEFAULT;
651 child->pos.rcNormalPosition.top = CW_USEDEFAULT;
652 child->pos.rcNormalPosition.right = CW_USEDEFAULT;
653 child->pos.rcNormalPosition.bottom = CW_USEDEFAULT;
655 child->focus_pane = 0;
656 child->split_pos = 200;
657 child->sortOrder = SORT_NAME;
658 child->header_wdths_ok = FALSE;
660 lstrcpy(child->path, path);
662 _tsplitpath(path, drv, dir, name, ext);
664 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
667 root->drive_type = GetDriveType(path);
669 lstrcat(drv, _T("/"));
670 lstrcpy(root->volname, _T("root fs"));
672 lstrcpy(root->fs, _T("unixfs"));
674 lstrcpy(root->path, _T("/"));
675 entry = read_tree_unix(root, path, child->sortOrder);
680 root->drive_type = GetDriveType(path);
682 lstrcat(drv, _T("\\"));
683 GetVolumeInformation(drv, root->volname, _MAX_FNAME, 0, 0, &root->fs_flags, root->fs, _MAX_DIR);
685 lstrcpy(root->path, drv);
686 entry = read_tree_win(root, path, child->sortOrder);
689 //@@lstrcpy(root->entry.data.cFileName, drv);
690 wsprintf(root->entry.data.cFileName, _T("%s - %s"), drv, root->fs);
692 root->entry.data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
694 child->left.root = &root->entry;
696 set_curdir(child, entry);
702 // recursively free all child entries
703 static void free_entries(Entry* parent)
705 Entry *entry, *next=parent->down;
720 // free all memory associated with a child window
721 static void free_child_window(ChildWnd* child)
723 free_entries(&child->root.entry);
728 // get full path of specified directory entry
729 static void get_path(Entry* dir, PTSTR path)
735 for(entry=dir; entry; level++) {
736 LPCTSTR name = entry->data.cFileName;
740 for(l=0; *s && *s!=_T('/') && *s!=_T('\\'); s++)
744 memmove(path+l+1, path, len*sizeof(TCHAR));
745 memcpy(path+1, name, l*sizeof(TCHAR));
748 #ifndef _NO_EXTENSIONS
757 memmove(path+l, path, len*sizeof(TCHAR));
758 memcpy(path, name, l*sizeof(TCHAR));
765 #ifndef _NO_EXTENSIONS
767 path[len++] = _T('/');
770 path[len++] = _T('\\');
773 path[len] = _T('\0');
777 static void resize_frame_rect(HWND hwnd, PRECT prect)
782 if (IsWindowVisible(Globals.htoolbar)) {
783 SendMessage(Globals.htoolbar, WM_SIZE, 0, 0);
784 GetClientRect(Globals.htoolbar, &rt);
785 prect->top = rt.bottom+3;
786 prect->bottom -= rt.bottom+3;
789 if (IsWindowVisible(Globals.hdrivebar)) {
790 SendMessage(Globals.hdrivebar, WM_SIZE, 0, 0);
791 GetClientRect(Globals.hdrivebar, &rt);
792 new_top = --prect->top + rt.bottom+3;
793 MoveWindow(Globals.hdrivebar, 0, prect->top, rt.right, new_top, TRUE);
794 prect->top = new_top;
795 prect->bottom -= rt.bottom+2;
798 if (IsWindowVisible(Globals.hstatusbar)) {
799 int parts[] = {300, 500};
801 SendMessage(Globals.hstatusbar, WM_SIZE, 0, 0);
802 SendMessage(Globals.hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
803 GetClientRect(Globals.hstatusbar, &rt);
804 prect->bottom -= rt.bottom;
807 MoveWindow(Globals.hmdiclient, prect->left-1,prect->top-1,prect->right+2,prect->bottom+1, TRUE);
810 static void resize_frame(HWND hwnd, int cx, int cy)
812 RECT rect = {0, 0, cx, cy};
814 resize_frame_rect(hwnd, &rect);
817 static void resize_frame_client(HWND hwnd)
821 GetClientRect(hwnd, &rect);
823 resize_frame_rect(hwnd, &rect);
827 static HHOOK hcbthook;
828 static ChildWnd* newchild = NULL;
830 LRESULT CALLBACK CBTProc(int code, WPARAM wparam, LPARAM lparam)
832 if (code==HCBT_CREATEWND && newchild) {
833 ChildWnd* child = newchild;
836 child->hwnd = (HWND) wparam;
837 SetWindowLong(child->hwnd, GWL_USERDATA, (LPARAM)child);
840 return CallNextHookEx(hcbthook, code, wparam, lparam);
843 static HWND create_child_window(ChildWnd* child)
845 MDICREATESTRUCT mcs = {
846 WINEFILETREE, (LPTSTR)child->path, Globals.hInstance,
847 child->pos.rcNormalPosition.left, child->pos.rcNormalPosition.top,
848 child->pos.rcNormalPosition.right-child->pos.rcNormalPosition.left,
849 child->pos.rcNormalPosition.bottom-child->pos.rcNormalPosition.top,
850 0/*style*/, 0/*lParam*/
854 hcbthook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId());
857 child->hwnd = (HWND) SendMessage(Globals.hmdiclient, WM_MDICREATE, 0, (LPARAM)&mcs);
861 UnhookWindowsHookEx(hcbthook);
863 idx = ListBox_FindItemData(child->left.hwnd, ListBox_GetCurSel(child->left.hwnd), child->left.cur);
864 ListBox_SetCurSel(child->left.hwnd, idx);
870 struct ExecuteDialog {
876 static BOOL CALLBACK ExecuteDialogWndProg(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
878 static struct ExecuteDialog* dlg;
882 dlg = (struct ExecuteDialog*) lparam;
886 int id = (int)wparam;
889 GetWindowText(GetDlgItem(hwnd, 201), dlg->cmd, MAX_PATH);
890 dlg->cmdshow = Button_GetState(GetDlgItem(hwnd,214))&BST_CHECKED?
891 SW_SHOWMINIMIZED: SW_SHOWNORMAL;
893 } else if (id == IDCANCEL)
903 #ifndef _NO_EXTENSIONS
905 static struct FullScreenParameters {
913 void frame_get_clientspace(HWND hwnd, PRECT prect)
918 GetClientRect(hwnd, prect);
922 GetWindowPlacement(hwnd, &wp);
924 prect->left = prect->top = 0;
925 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
926 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
927 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
928 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
929 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
932 if (IsWindowVisible(Globals.htoolbar)) {
933 GetClientRect(Globals.htoolbar, &rt);
934 prect->top += rt.bottom+2;
937 if (IsWindowVisible(Globals.hdrivebar)) {
938 GetClientRect(Globals.hdrivebar, &rt);
939 prect->top += rt.bottom+2;
942 if (IsWindowVisible(Globals.hstatusbar)) {
943 GetClientRect(Globals.hstatusbar, &rt);
944 prect->bottom -= rt.bottom;
948 static BOOL toggle_fullscreen(HWND hwnd)
952 if ((g_fullscreen.mode=!g_fullscreen.mode)) {
953 GetWindowRect(hwnd, &g_fullscreen.orgPos);
954 g_fullscreen.wasZoomed = IsZoomed(hwnd);
956 Frame_CalcFrameClient(hwnd, &rt);
957 ClientToScreen(hwnd, (LPPOINT)&rt.left);
958 ClientToScreen(hwnd, (LPPOINT)&rt.right);
960 rt.left = g_fullscreen.orgPos.left-rt.left;
961 rt.top = g_fullscreen.orgPos.top-rt.top;
962 rt.right = GetSystemMetrics(SM_CXSCREEN)+g_fullscreen.orgPos.right-rt.right;
963 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+g_fullscreen.orgPos.bottom-rt.bottom;
965 MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
967 MoveWindow(hwnd, g_fullscreen.orgPos.left, g_fullscreen.orgPos.top,
968 g_fullscreen.orgPos.right-g_fullscreen.orgPos.left,
969 g_fullscreen.orgPos.bottom-g_fullscreen.orgPos.top, TRUE);
971 if (g_fullscreen.wasZoomed)
972 ShowWindow(hwnd, WS_MAXIMIZE);
975 return g_fullscreen.mode;
978 static void fullscreen_move(HWND hwnd)
981 GetWindowRect(hwnd, &pos);
983 Frame_CalcFrameClient(hwnd, &rt);
984 ClientToScreen(hwnd, (LPPOINT)&rt.left);
985 ClientToScreen(hwnd, (LPPOINT)&rt.right);
987 rt.left = pos.left-rt.left;
988 rt.top = pos.top-rt.top;
989 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
990 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
992 MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
998 static void toggle_child(HWND hwnd, UINT cmd, HWND hchild)
1000 BOOL vis = IsWindowVisible(hchild);
1002 CheckMenuItem(Globals.hMenuOptions, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
1004 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
1006 #ifndef _NO_EXTENSIONS
1007 if (g_fullscreen.mode)
1008 fullscreen_move(hwnd);
1011 resize_frame_client(hwnd);
1014 BOOL activate_drive_window(LPCTSTR path)
1016 TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
1019 _tsplitpath(path, drv1, 0, 0, 0);
1021 // search for a already open window for the same drive
1022 for(child_wnd=GetNextWindow(Globals.hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1023 ChildWnd* child = (ChildWnd*) GetWindowLong(child_wnd, GWL_USERDATA);
1026 _tsplitpath(child->root.path, drv2, 0, 0, 0);
1028 if (!lstrcmpi(drv2, drv1)) {
1029 SendMessage(Globals.hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1031 if (IsMinimized(child_wnd))
1032 ShowWindow(child_wnd, SW_SHOWNORMAL);
1042 LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
1046 DestroyWindow(hwnd);
1054 UINT cmd = LOWORD(wparam);
1055 HWND hwndClient = (HWND) SendMessage(Globals.hmdiclient, WM_MDIGETACTIVE, 0, 0);
1057 if (SendMessage(hwndClient, WM_DISPATCH_COMMAND, wparam, lparam))
1060 if (cmd>=ID_DRIVE_FIRST && cmd<=ID_DRIVE_FIRST+0xFF) {
1061 TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
1063 LPCTSTR root = Globals.drives;
1066 for(i=cmd-ID_DRIVE_FIRST; i--; root++)
1070 if (activate_drive_window(root))
1073 _tsplitpath(root, drv, 0, 0, 0);
1075 if (!SetCurrentDirectory(drv)) {
1076 display_error(hwnd, GetLastError());
1080 GetCurrentDirectory(MAX_PATH, path); //@@ letztes Verzeichnis pro Laufwerk speichern
1081 child = alloc_child_window(path);
1083 if (!create_child_window(child))
1085 } else switch(cmd) {
1090 case ID_WINDOW_NEW: {
1091 TCHAR path[MAX_PATH];
1094 GetCurrentDirectory(MAX_PATH, path);
1095 child = alloc_child_window(path);
1097 if (!create_child_window(child))
1101 case ID_WINDOW_CASCADE:
1102 SendMessage(Globals.hmdiclient, WM_MDICASCADE, 0, 0);
1105 case ID_WINDOW_TILE_HORZ:
1106 SendMessage(Globals.hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
1109 case ID_WINDOW_TILE_VERT:
1110 SendMessage(Globals.hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
1113 case ID_WINDOW_ARRANGE:
1114 SendMessage(Globals.hmdiclient, WM_MDIICONARRANGE, 0, 0);
1117 case ID_VIEW_TOOL_BAR:
1118 toggle_child(hwnd, cmd, Globals.htoolbar);
1121 case ID_VIEW_DRIVE_BAR:
1122 toggle_child(hwnd, cmd, Globals.hdrivebar);
1125 case ID_VIEW_STATUSBAR:
1126 toggle_child(hwnd, cmd, Globals.hstatusbar);
1130 struct ExecuteDialog dlg = {{0}};
1131 if (DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(IDD_EXECUTE), hwnd, ExecuteDialogWndProg, (LPARAM)&dlg) == IDOK)
1132 ShellExecute(hwnd, _T("open")/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow);
1136 WinHelp(hwnd, _T("winfile"), HELP_INDEX, 0);
1139 #ifndef _NO_EXTENSIONS
1140 case ID_VIEW_FULLSCREEN:
1141 CheckMenuItem(Globals.hMenuOptions, cmd, toggle_fullscreen(hwnd)?MF_CHECKED:0);
1145 case ID_DRIVE_UNIX_FS: {
1146 TCHAR path[MAX_PATH];
1149 if (activate_drive_window(_T("/")))
1152 getcwd(path, MAX_PATH);
1153 child = alloc_child_window(path);
1155 if (!create_child_window(child))
1161 //TODO: There are even more menu items!
1163 #ifndef _NO_EXTENSIONS
1165 WineLicense(Globals.hMainWnd);
1168 case ID_NO_WARRANTY:
1169 WineWarranty(Globals.hMainWnd);
1173 ShellAbout(hwnd, _T("WINE"), _T("Winefile"), 0);
1178 /*@@if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE)
1179 STRING_SelectLanguageByNumber(wParam - PM_FIRST_LANGUAGE);
1180 else */if ((cmd<IDW_FIRST_CHILD || cmd>=IDW_FIRST_CHILD+0x100) &&
1181 (cmd<SC_SIZE || cmd>SC_RESTORE))
1182 MessageBox(hwnd, _T("Not yet implemented"), _T("Winefile"), MB_OK);
1184 return DefFrameProc(hwnd, Globals.hmdiclient, nmsg, wparam, lparam);
1189 resize_frame(hwnd, LOWORD(lparam), HIWORD(lparam));
1190 break; // do not pass message to DefFrameProc
1192 #ifndef _NO_EXTENSIONS
1193 case WM_GETMINMAXINFO: {
1194 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
1196 lpmmi->ptMaxTrackSize.x <<= 1;//2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN
1197 lpmmi->ptMaxTrackSize.y <<= 1;//2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN
1200 case FRM_CALC_CLIENT:
1201 frame_get_clientspace(hwnd, (PRECT)lparam);
1206 return DefFrameProc(hwnd, Globals.hmdiclient, nmsg, wparam, lparam);
1213 const static LPTSTR g_pos_names[COLUMNS] = {
1218 #ifndef _NO_EXTENSIONS
1225 #ifndef _NO_EXTENSIONS
1230 const static int g_pos_align[] = {
1235 #ifndef _NO_EXTENSIONS
1239 HDF_CENTER, // Links
1241 HDF_CENTER, // Attributes
1242 #ifndef _NO_EXTENSIONS
1243 HDF_LEFT // Security
1247 static void resize_tree(ChildWnd* child, int cx, int cy)
1249 HDWP hdwp = BeginDeferWindowPos(4);
1250 RECT rt = {0, 0, cx, cy};
1252 cx = child->split_pos + SPLIT_WIDTH/2;
1254 #ifndef _NO_EXTENSIONS
1257 HD_LAYOUT hdl = {&rt, &wp};
1259 Header_Layout(child->left.hwndHeader, &hdl);
1261 DeferWindowPos(hdwp, child->left.hwndHeader, wp.hwndInsertAfter,
1262 wp.x-1, wp.y, child->split_pos-SPLIT_WIDTH/2+1, wp.cy, wp.flags);
1263 DeferWindowPos(hdwp, child->right.hwndHeader, wp.hwndInsertAfter,
1264 rt.left+cx+1, wp.y, wp.cx-cx+2, wp.cy, wp.flags);
1268 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);
1269 DeferWindowPos(hdwp, child->right.hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
1271 EndDeferWindowPos(hdwp);
1275 #ifndef _NO_EXTENSIONS
1277 static HWND create_header(HWND parent, Pane* pane, int id)
1279 HD_ITEM hdi = {HDI_TEXT|HDI_WIDTH|HDI_FORMAT};
1282 HWND hwnd = CreateWindow(WC_HEADER, 0, WS_CHILD|WS_VISIBLE|HDS_HORZ/*TODO: |HDS_BUTTONS + sort orders*/,
1283 0, 0, 0, 0, parent, (HMENU)id, Globals.hInstance, 0);
1287 SendMessage(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), FALSE);
1289 for(idx=0; idx<COLUMNS; idx++) {
1290 hdi.pszText = g_pos_names[idx];
1291 hdi.fmt = HDF_STRING | g_pos_align[idx];
1292 hdi.cxy = pane->widths[idx];
1293 Header_InsertItem(hwnd, idx, &hdi);
1302 static void init_output(HWND hwnd)
1306 HDC hdc = GetDC(hwnd);
1308 if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, _T("1000"), 0, b, 16) > 4)
1309 Globals.num_sep = b[1];
1311 Globals.num_sep = _T('.');
1313 old_font = SelectFont(hdc, Globals.hfont);
1314 GetTextExtentPoint32(hdc, _T(" "), 1, &Globals.spaceSize);
1315 SelectFont(hdc, old_font);
1316 ReleaseDC(hwnd, hdc);
1319 static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol);
1322 // calculate prefered width for all visible columns
1324 static BOOL calc_widths(Pane* pane, BOOL anyway)
1326 int col, x, cx, spc=3*Globals.spaceSize.cx;
1327 int entries = ListBox_GetCount(pane->hwnd);
1328 int orgWidths[COLUMNS];
1329 int orgPositions[COLUMNS+1];
1335 memcpy(orgWidths, pane->widths, sizeof(orgWidths));
1336 memcpy(orgPositions, pane->positions, sizeof(orgPositions));
1339 for(col=0; col<COLUMNS; col++)
1340 pane->widths[col] = 0;
1342 hdc = GetDC(pane->hwnd);
1343 hfontOld = SelectFont(hdc, Globals.hfont);
1345 for(cnt=0; cnt<entries; cnt++) {
1346 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, cnt);
1348 DRAWITEMSTRUCT dis = {0/*CtlType*/, 0/*CtlID*/,
1349 0/*itemID*/, 0/*itemAction*/, 0/*itemState*/,
1350 pane->hwnd/*hwndItem*/, hdc};
1352 draw_item(pane, &dis, entry, COLUMNS);
1355 SelectObject(hdc, hfontOld);
1356 ReleaseDC(pane->hwnd, hdc);
1359 for(col=0; col<COLUMNS; col++) {
1360 pane->positions[col] = x;
1361 cx = pane->widths[col];
1366 if (cx < IMAGE_WIDTH)
1369 pane->widths[col] = cx;
1375 pane->positions[COLUMNS] = x;
1377 ListBox_SetHorizontalExtent(pane->hwnd, x);
1380 if (!memcmp(orgWidths, pane->widths, sizeof(orgWidths)))
1383 // don't move, if only collapsing an entry
1384 if (!anyway && pane->widths[0]<orgWidths[0] &&
1385 !memcmp(orgWidths+1, pane->widths+1, sizeof(orgWidths)-sizeof(int))) {
1386 pane->widths[0] = orgWidths[0];
1387 memcpy(pane->positions, orgPositions, sizeof(orgPositions));
1392 InvalidateRect(pane->hwnd, 0, TRUE);
1398 // calculate one prefered column width
1400 static void calc_single_width(Pane* pane, int col)
1404 int entries = ListBox_GetCount(pane->hwnd);
1408 pane->widths[col] = 0;
1410 hdc = GetDC(pane->hwnd);
1411 hfontOld = SelectFont(hdc, Globals.hfont);
1413 for(cnt=0; cnt<entries; cnt++) {
1414 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, cnt);
1415 DRAWITEMSTRUCT dis = {0, 0, 0, 0, 0, pane->hwnd, hdc};
1417 draw_item(pane, &dis, entry, col);
1420 SelectObject(hdc, hfontOld);
1421 ReleaseDC(pane->hwnd, hdc);
1423 cx = pane->widths[col];
1426 cx += 3*Globals.spaceSize.cx;
1428 if (cx < IMAGE_WIDTH)
1432 pane->widths[col] = cx;
1434 x = pane->positions[col] + cx;
1436 for(; col<COLUMNS; ) {
1437 pane->positions[++col] = x;
1438 x += pane->widths[col];
1441 ListBox_SetHorizontalExtent(pane->hwnd, x);
1445 // insert listbox entries after index idx
1447 static void insert_entries(Pane* pane, Entry* parent, int idx)
1449 Entry* entry = parent;
1454 ShowWindow(pane->hwnd, SW_HIDE);
1456 for(; entry; entry=entry->next) {
1458 if (pane->treePane && !(entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
1462 // don't display entries "." and ".." in the left pane
1463 if (pane->treePane && (entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
1464 && entry->data.cFileName[0]==_T('.'))
1466 #ifndef _NO_EXTENSIONS
1467 entry->data.cFileName[1]==_T('\0') ||
1469 (entry->data.cFileName[1]==_T('.') && entry->data.cFileName[2]==_T('\0')))
1475 ListBox_InsertItemData(pane->hwnd, idx, entry);
1477 if (pane->treePane && entry->expanded)
1478 insert_entries(pane, entry->down, idx);
1481 ShowWindow(pane->hwnd, SW_SHOW);
1485 static WNDPROC g_orgTreeWndProc;
1487 static void create_tree_window(HWND parent, Pane* pane, int id, int id_header)
1489 static int s_init = 0;
1490 Entry* entry = pane->root;
1492 pane->hwnd = CreateWindow(_T("ListBox"), _T(""), WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|
1493 LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED|LBS_NOTIFY,
1494 0, 0, 0, 0, parent, (HMENU)id, Globals.hInstance, 0);
1496 SetWindowLong(pane->hwnd, GWL_USERDATA, (LPARAM)pane);
1497 g_orgTreeWndProc = SubclassWindow(pane->hwnd, TreeWndProc);
1499 SendMessage(pane->hwnd, WM_SETFONT, (WPARAM)Globals.hfont, FALSE);
1501 // insert entries into listbox
1503 insert_entries(pane, entry, -1);
1505 // calculate column widths
1508 init_output(pane->hwnd);
1511 calc_widths(pane, TRUE);
1513 #ifndef _NO_EXTENSIONS
1514 pane->hwndHeader = create_header(parent, pane, id_header);
1519 static void InitChildWindow(ChildWnd* child)
1521 create_tree_window(child->hwnd, &child->left, IDW_TREE_LEFT, IDW_HEADER_LEFT);
1522 create_tree_window(child->hwnd, &child->right, IDW_TREE_RIGHT, IDW_HEADER_RIGHT);
1526 static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols)
1534 if (!ft->dwLowDateTime && !ft->dwHighDateTime)
1537 if (!FileTimeToLocalFileTime(ft, &lft))
1538 {err: _tcscpy(buffer,_T("???")); return;}
1540 if (!FileTimeToSystemTime(&lft, &systime))
1543 if (visible_cols & COL_DATE) {
1544 len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer, BUFFER_LEN);
1549 if (visible_cols & COL_TIME) {
1551 buffer[len-1] = ' ';
1553 buffer[len++] = ' ';
1555 if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len))
1556 buffer[len] = _T('\0');
1561 static void calc_width(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1565 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX);
1567 if (rt.right > pane->widths[col])
1568 pane->widths[col] = rt.right;
1571 static void calc_tabbed_width(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1575 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1576 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1578 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
1581 if (rt.right > pane->widths[col])
1582 pane->widths[col] = rt.right;
1586 static void output_text(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str, DWORD flags)
1588 int x = dis->rcItem.left;
1589 RECT rt = {x+pane->positions[col]+Globals.spaceSize.cx, dis->rcItem.top, x+pane->positions[col+1]-Globals.spaceSize.cx, dis->rcItem.bottom};
1591 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|flags);
1594 static void output_tabbed_text(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1596 int x = dis->rcItem.left;
1597 RECT rt = {x+pane->positions[col]+Globals.spaceSize.cx, dis->rcItem.top, x+pane->positions[col+1]-Globals.spaceSize.cx, dis->rcItem.bottom};
1599 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1600 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1602 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
1605 static void output_number(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1607 int x = dis->rcItem.left;
1608 RECT rt = {x+pane->positions[col]+Globals.spaceSize.cx, dis->rcItem.top, x+pane->positions[col+1]-Globals.spaceSize.cx, dis->rcItem.bottom};
1617 // insert number separator characters
1618 pos = lstrlen(s) % 3;
1624 *d++ = Globals.num_sep;
1628 DrawText(dis->hDC, b, d-b, &rt, DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX|DT_END_ELLIPSIS);
1632 static int is_exe_file(LPCTSTR ext)
1634 const static LPCTSTR executable_extensions[] = {
1639 #ifndef _NO_EXTENSIONS
1647 TCHAR ext_buffer[_MAX_EXT];
1652 for(s=ext+1,d=ext_buffer; (*d=tolower(*s)); s++)
1655 for(p=executable_extensions; *p; p++)
1656 if (!_tcscmp(ext_buffer, *p))
1662 static int is_registered_type(LPCTSTR ext)
1670 static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
1672 TCHAR buffer[BUFFER_LEN];
1674 int visible_cols = pane->visible_cols;
1675 COLORREF bkcolor, textcolor;
1676 RECT focusRect = dis->rcItem;
1679 #ifndef _NO_EXTENSIONS
1686 attrs = entry->data.dwFileAttributes;
1688 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
1689 if (entry->data.cFileName[0]==_T('.') && entry->data.cFileName[1]==_T('.')
1690 && entry->data.cFileName[2]==_T('\0'))
1691 img = IMG_FOLDER_UP;
1692 #ifndef _NO_EXTENSIONS
1693 else if (entry->data.cFileName[0]==_T('.') && entry->data.cFileName[1]==_T('\0'))
1694 img = IMG_FOLDER_CUR;
1697 #ifdef _NO_EXTENSIONS
1700 (pane->treePane && (dis->itemState&ODS_FOCUS)))
1701 img = IMG_OPEN_FOLDER;
1705 LPCTSTR ext = _tcsrchr(entry->data.cFileName, '.');
1709 if (is_exe_file(ext))
1710 img = IMG_EXECUTABLE;
1711 else if (is_registered_type(ext))
1721 if (pane->treePane) {
1723 img_pos = dis->rcItem.left + entry->level*(IMAGE_WIDTH+Globals.spaceSize.cx);
1725 if (calcWidthCol == -1) {
1727 int y = dis->rcItem.top + IMAGE_HEIGHT/2;
1729 RECT rt_clip = {dis->rcItem.left, dis->rcItem.top, dis->rcItem.left+pane->widths[col], dis->rcItem.bottom};
1730 HRGN hrgn_org = CreateRectRgn(0, 0, 0, 0);
1731 HRGN hrgn = CreateRectRgnIndirect(&rt_clip);
1733 if (!GetClipRgn(dis->hDC, hrgn_org)) {
1734 DeleteObject(hrgn_org);
1738 // HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN));
1739 ExtSelectClipRgn(dis->hDC, hrgn, RGN_AND);
1742 if ((up=entry->up) != NULL) {
1743 MoveToEx(dis->hDC, img_pos-IMAGE_WIDTH/2, y, 0);
1744 LineTo(dis->hDC, img_pos-2, y);
1746 x = img_pos - IMAGE_WIDTH/2;
1749 x -= IMAGE_WIDTH+Globals.spaceSize.cx;
1753 && (up->next->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
1756 MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
1757 LineTo(dis->hDC, x, dis->rcItem.bottom);
1759 } while((up=up->up) != NULL);
1762 x = img_pos - IMAGE_WIDTH/2;
1764 MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
1765 LineTo(dis->hDC, x, y);
1769 && (entry->next->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
1772 LineTo(dis->hDC, x, dis->rcItem.bottom);
1774 if (entry->down && entry->expanded) {
1775 x += IMAGE_WIDTH+Globals.spaceSize.cx;
1776 MoveToEx(dis->hDC, x, dis->rcItem.top+IMAGE_HEIGHT, 0);
1777 LineTo(dis->hDC, x, dis->rcItem.bottom);
1780 SelectClipRgn(dis->hDC, hrgn_org);
1781 if (hrgn_org) DeleteObject(hrgn_org);
1782 // SelectObject(dis->hDC, holdPen);
1783 } else if (calcWidthCol==col || calcWidthCol==COLUMNS) {
1784 int right = img_pos + IMAGE_WIDTH - Globals.spaceSize.cx;
1786 if (right > pane->widths[col])
1787 pane->widths[col] = right;
1790 img_pos = dis->rcItem.left;
1793 img_pos = dis->rcItem.left;
1795 if (calcWidthCol==col || calcWidthCol==COLUMNS)
1796 pane->widths[col] = IMAGE_WIDTH;
1799 if (calcWidthCol == -1) {
1800 focusRect.left = img_pos -2;
1802 #ifdef _NO_EXTENSIONS
1803 if (pane->treePane && entry) {
1806 DrawText(dis->hDC, entry->data.cFileName, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX);
1808 focusRect.right = dis->rcItem.left+pane->positions[col+1]+Globals.spaceSize.cx + rt.right +2;
1812 if (attrs & FILE_ATTRIBUTE_COMPRESSED)
1813 textcolor = COLOR_COMPRESSED;
1816 textcolor = RGB(0,0,0);
1818 if (dis->itemState & ODS_FOCUS) {
1819 textcolor = RGB(255,255,255);
1820 bkcolor = COLOR_SELECTION;
1822 bkcolor = RGB(255,255,255);
1825 hbrush = CreateSolidBrush(bkcolor);
1826 FillRect(dis->hDC, &focusRect, hbrush);
1827 DeleteObject(hbrush);
1829 SetBkMode(dis->hDC, TRANSPARENT);
1830 SetTextColor(dis->hDC, textcolor);
1832 cx = pane->widths[col];
1834 if (cx && img!=IMG_NONE) {
1835 if (cx > IMAGE_WIDTH)
1838 ImageList_DrawEx(Globals.himl, img, dis->hDC,
1839 img_pos, dis->rcItem.top, cx,
1840 IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL);
1847 #ifdef _NO_EXTENSIONS
1848 if (img >= IMG_FOLDER_UP)
1855 if (calcWidthCol == -1)
1856 output_text(pane, dis, col, entry->data.cFileName, 0);
1857 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1858 calc_width(pane, dis, col, entry->data.cFileName);
1862 #ifdef _NO_EXTENSIONS
1863 if (!pane->treePane) {
1866 // display file size
1867 if (visible_cols & COL_SIZE) {
1868 #ifdef _NO_EXTENSIONS
1869 if (!(attrs&FILE_ATTRIBUTE_DIRECTORY))
1874 *(DWORD*)(&size) = entry->data.nFileSizeLow; //TODO: platform spefific
1875 *(((DWORD*)&size)+1) = entry->data.nFileSizeHigh;
1877 _stprintf(buffer, _T("%") LONGLONGARG _T("d"), size);
1879 if (calcWidthCol == -1)
1880 output_number(pane, dis, col, buffer);
1881 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1882 calc_width(pane, dis, col, buffer);//TODO: not ever time enough
1888 // display file date
1889 if (visible_cols & (COL_DATE|COL_TIME)) {
1890 #ifndef _NO_EXTENSIONS
1891 format_date(&entry->data.ftCreationTime, buffer, visible_cols);
1892 if (calcWidthCol == -1)
1893 output_text(pane, dis, col, buffer, 0);
1894 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1895 calc_width(pane, dis, col, buffer);
1898 format_date(&entry->data.ftLastAccessTime, buffer, visible_cols);
1899 if (calcWidthCol == -1)
1900 output_text(pane, dis, col, buffer, 0);
1901 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1902 calc_width(pane, dis, col, buffer);
1906 format_date(&entry->data.ftLastWriteTime, buffer, visible_cols);
1907 if (calcWidthCol == -1)
1908 output_text(pane, dis, col, buffer, 0);
1909 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1910 calc_width(pane, dis, col, buffer);
1914 #ifndef _NO_EXTENSIONS
1915 if (entry->bhfi_valid) {
1916 ((DWORD*)&index)[0] = entry->bhfi.nFileIndexLow; //TODO: platform spefific
1917 ((DWORD*)&index)[1] = entry->bhfi.nFileIndexHigh;
1919 if (visible_cols & COL_INDEX) {
1920 _stprintf(buffer, _T("%") LONGLONGARG _T("X"), index);
1921 if (calcWidthCol == -1)
1922 output_text(pane, dis, col, buffer, DT_RIGHT);
1923 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1924 calc_width(pane, dis, col, buffer);
1928 if (visible_cols & COL_LINKS) {
1929 wsprintf(buffer, _T("%d"), entry->bhfi.nNumberOfLinks);
1930 if (calcWidthCol == -1)
1931 output_text(pane, dis, col, buffer, DT_CENTER);
1932 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1933 calc_width(pane, dis, col, buffer);
1940 // show file attributes
1941 if (visible_cols & COL_ATTRIBUTES) {
1942 #ifdef _NO_EXTENSIONS
1943 _tcscpy(buffer, _T(" \t \t \t \t "));
1945 _tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
1948 if (attrs & FILE_ATTRIBUTE_NORMAL) buffer[ 0] = 'N';
1950 if (attrs & FILE_ATTRIBUTE_READONLY) buffer[ 2] = 'R';
1951 if (attrs & FILE_ATTRIBUTE_HIDDEN) buffer[ 4] = 'H';
1952 if (attrs & FILE_ATTRIBUTE_SYSTEM) buffer[ 6] = 'S';
1953 if (attrs & FILE_ATTRIBUTE_ARCHIVE) buffer[ 8] = 'A';
1954 if (attrs & FILE_ATTRIBUTE_COMPRESSED) buffer[10] = 'C';
1955 #ifndef _NO_EXTENSIONS
1956 if (attrs & FILE_ATTRIBUTE_DIRECTORY) buffer[12] = 'D';
1957 if (attrs & FILE_ATTRIBUTE_ENCRYPTED) buffer[14] = 'E';
1958 if (attrs & FILE_ATTRIBUTE_TEMPORARY) buffer[16] = 'T';
1959 if (attrs & FILE_ATTRIBUTE_SPARSE_FILE) buffer[18] = 'P';
1960 if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) buffer[20] = 'Q';
1961 if (attrs & FILE_ATTRIBUTE_OFFLINE) buffer[22] = 'O';
1962 if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) buffer[24] = 'X';
1966 if (calcWidthCol == -1)
1967 output_tabbed_text(pane, dis, col, buffer);
1968 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1969 calc_tabbed_width(pane, dis, col, buffer);
1975 if (flags.security) {
1976 DWORD rights = get_access_mask();
1978 tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
1980 if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
1981 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
1982 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
1983 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
1984 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
1985 if (rights & FILE_EXECUTE) buffer[12] = 'X';
1986 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
1987 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
1988 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
1989 if (rights & WRITE_DAC) buffer[22] = 'C';
1990 if (rights & WRITE_OWNER) buffer[24] = 'O';
1991 if (rights & SYNCHRONIZE) buffer[26] = 'S';
1993 output_text(dis, col++, buffer, DT_LEFT, 3, psize);
1996 if (flags.description) {
1997 get_description(buffer);
1998 output_text(dis, col++, buffer, 0, psize);
2002 #ifdef _NO_EXTENSIONS
2006 if ((dis->itemState&ODS_FOCUS) && calcWidthCol==-1) {
2007 // Currently [04/2000] Wine neither behaves exactly the same
2008 // way as WIN 95 nor like Windows NT...
2013 if (!(GetVersion() & 0x80000000)) { // Windows NT?
2014 LOGBRUSH lb = {PS_SOLID, RGB(255,255,255)};
2015 hpen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, 0);
2017 hpen = CreatePen(PS_DOT, 0, RGB(255,255,255));
2019 lastPen = SelectPen(dis->hDC, hpen);
2020 lastBrush = SelectObject(dis->hDC, GetStockObject(HOLLOW_BRUSH));
2021 SetROP2(dis->hDC, R2_XORPEN);
2022 Rectangle(dis->hDC, focusRect.left, focusRect.top, focusRect.right, focusRect.bottom);
2023 SelectObject(dis->hDC, lastBrush);
2024 SelectObject(dis->hDC, lastPen);
2031 #ifdef _NO_EXTENSIONS
2033 static void draw_splitbar(HWND hwnd, int x)
2036 HDC hdc = GetDC(hwnd);
2038 GetClientRect(hwnd, &rt);
2040 rt.left = x - SPLIT_WIDTH/2;
2041 rt.right = x + SPLIT_WIDTH/2+1;
2043 InvertRect(hdc, &rt);
2045 ReleaseDC(hwnd, hdc);
2051 #ifndef _NO_EXTENSIONS
2053 static void set_header(Pane* pane)
2056 int scroll_pos = GetScrollPos(pane->hwnd, SB_HORZ);
2059 item.mask = HDI_WIDTH;
2062 for(; x+pane->widths[i]<scroll_pos && i<COLUMNS; i++) {
2063 x += pane->widths[i];
2064 Header_SetItem(pane->hwndHeader, i, &item);
2068 x += pane->widths[i];
2069 item.cxy = x - scroll_pos;
2070 Header_SetItem(pane->hwndHeader, i++, &item);
2072 for(; i<COLUMNS; i++) {
2073 item.cxy = pane->widths[i];
2074 x += pane->widths[i];
2075 Header_SetItem(pane->hwndHeader, i, &item);
2080 static LRESULT pane_notify(Pane* pane, NMHDR* pnmh)
2082 switch(pnmh->code) {
2084 case HDN_ENDTRACK: {
2085 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
2086 int idx = phdn->iItem;
2087 int dx = phdn->pitem->cxy - pane->widths[idx];
2091 GetClientRect(pane->hwnd, &clnt);
2093 // move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB)
2094 Header_SetItem(pane->hwndHeader, idx, phdn->pitem);
2096 pane->widths[idx] += dx;
2098 for(i=idx; ++i<=COLUMNS; )
2099 pane->positions[i] += dx;
2102 int scroll_pos = GetScrollPos(pane->hwnd, SB_HORZ);
2103 RECT rt_scr = {pane->positions[idx+1]-scroll_pos, 0, clnt.right, clnt.bottom};
2104 RECT rt_clip = {pane->positions[idx]-scroll_pos, 0, clnt.right, clnt.bottom};
2106 if (rt_scr.left < 0) rt_scr.left = 0;
2107 if (rt_clip.left < 0) rt_clip.left = 0;
2109 ScrollWindowEx(pane->hwnd, dx, 0, &rt_scr, &rt_clip, 0, 0, SW_INVALIDATE);
2111 rt_clip.right = pane->positions[idx+1];
2112 RedrawWindow(pane->hwnd, &rt_clip, 0, RDW_INVALIDATE|RDW_UPDATENOW);
2114 if (pnmh->code == HDN_ENDTRACK) {
2115 ListBox_SetHorizontalExtent(pane->hwnd, pane->positions[COLUMNS]);
2117 if (GetScrollPos(pane->hwnd, SB_HORZ) != scroll_pos)
2125 case HDN_DIVIDERDBLCLICK: {
2126 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
2129 calc_single_width(pane, phdn->iItem);
2130 item.mask = HDI_WIDTH;
2131 item.cxy = pane->widths[phdn->iItem];
2133 Header_SetItem(pane->hwndHeader, phdn->iItem, &item);
2134 InvalidateRect(pane->hwnd, 0, TRUE);
2144 static void scan_entry(ChildWnd* child, Entry* entry)
2146 TCHAR path[MAX_PATH];
2147 int idx = ListBox_GetCurSel(child->left.hwnd);
2148 HCURSOR crsrOld = SetCursor(LoadCursor(0, IDC_WAIT));
2150 // delete sub entries in left pane
2152 LRESULT res = ListBox_GetItemData(child->left.hwnd, idx+1);
2153 Entry* sub = (Entry*) res;
2155 if (res==LB_ERR || !sub || sub->level<=entry->level)
2158 ListBox_DeleteString(child->left.hwnd, idx+1);
2162 ListBox_ResetContent(child->right.hwnd);
2165 free_entries(entry);
2167 // read contents from disk
2168 get_path(entry, path);
2169 read_directory(entry, path, child->sortOrder);
2171 // insert found entries in right pane
2172 insert_entries(&child->right, entry->down, -1);
2173 calc_widths(&child->right, FALSE);
2174 #ifndef _NO_EXTENSIONS
2175 set_header(&child->right);
2178 child->header_wdths_ok = FALSE;
2184 // expand a directory entry
2186 static BOOL expand_entry(ChildWnd* child, Entry* dir)
2191 if (!dir || dir->expanded || !dir->down)
2196 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='\0' && p->next) {
2199 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='.' &&
2200 p->data.cFileName[2]=='\0' && p->next)
2204 // no subdirectories ?
2205 if (!(p->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
2208 idx = ListBox_FindItemData(child->left.hwnd, 0, dir);
2210 dir->expanded = TRUE;
2212 // insert entries in left pane
2213 insert_entries(&child->left, p, idx);
2215 if (!child->header_wdths_ok) {
2216 if (calc_widths(&child->left, FALSE)) {
2217 #ifndef _NO_EXTENSIONS
2218 set_header(&child->left);
2221 child->header_wdths_ok = TRUE;
2229 static void collapse_entry(Pane* pane, Entry* dir)
2231 int idx = ListBox_FindItemData(pane->hwnd, 0, dir);
2233 ShowWindow(pane->hwnd, SW_HIDE);
2237 LRESULT res = ListBox_GetItemData(pane->hwnd, idx+1);
2238 Entry* sub = (Entry*) res;
2240 if (res==LB_ERR || !sub || sub->level<=dir->level)
2243 ListBox_DeleteString(pane->hwnd, idx+1);
2246 dir->expanded = FALSE;
2248 ShowWindow(pane->hwnd, SW_SHOW);
2252 static void set_curdir(ChildWnd* child, Entry* entry)
2254 TCHAR path[MAX_PATH];
2256 child->left.cur = entry;
2257 child->right.root = entry;
2258 child->right.cur = entry;
2260 if (!entry->scanned)
2261 scan_entry(child, entry);
2263 ListBox_ResetContent(child->right.hwnd);
2264 insert_entries(&child->right, entry->down, -1);
2265 calc_widths(&child->right, FALSE);
2266 #ifndef _NO_EXTENSIONS
2267 set_header(&child->right);
2271 get_path(entry, path);
2272 lstrcpy(child->path, path);
2273 SetWindowText(child->hwnd, path);
2274 SetCurrentDirectory(path);
2278 static void activate_entry(ChildWnd* child, Pane* pane)
2280 Entry* entry = pane->cur;
2285 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2286 int scanned_old = entry->scanned;
2289 scan_entry(child, entry);
2291 #ifndef _NO_EXTENSIONS
2292 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='\0')
2296 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='.' && entry->data.cFileName[2]=='\0') {
2297 entry = child->left.cur->up;
2298 collapse_entry(&child->left, entry);
2300 } else if (entry->expanded)
2301 collapse_entry(pane, child->left.cur);
2303 expand_entry(child, child->left.cur);
2305 if (!pane->treePane) focus_entry: {
2306 int idx = ListBox_FindItemData(child->left.hwnd, ListBox_GetCurSel(child->left.hwnd), entry);
2307 ListBox_SetCurSel(child->left.hwnd, idx);
2308 set_curdir(child, entry);
2313 calc_widths(pane, FALSE);
2315 #ifndef _NO_EXTENSIONS
2321 //TODO: start program, open document...
2327 static BOOL pane_command(Pane* pane, UINT cmd)
2331 if (pane->visible_cols) {
2332 pane->visible_cols = 0;
2333 calc_widths(pane, TRUE);
2334 #ifndef _NO_EXTENSIONS
2337 InvalidateRect(pane->hwnd, 0, TRUE);
2338 CheckMenuItem(Globals.hMenuView, ID_VIEW_NAME, MF_BYCOMMAND|MF_CHECKED);
2339 CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND);
2340 CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
2344 case ID_VIEW_ALL_ATTRIBUTES:
2345 if (pane->visible_cols != COL_ALL) {
2346 pane->visible_cols = COL_ALL;
2347 calc_widths(pane, TRUE);
2348 #ifndef _NO_EXTENSIONS
2351 InvalidateRect(pane->hwnd, 0, TRUE);
2352 CheckMenuItem(Globals.hMenuView, ID_VIEW_NAME, MF_BYCOMMAND);
2353 CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED);
2354 CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
2358 #ifndef _NO_EXTENSIONS
2359 case ID_PREFERED_SIZES: {
2360 calc_widths(pane, TRUE);
2362 InvalidateRect(pane->hwnd, 0, TRUE);
2366 // TODO: more command ids...
2376 LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
2378 static int last_split;
2380 ChildWnd* child = (ChildWnd*) GetWindowLong(hwnd, GWL_USERDATA);
2385 LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam;
2386 Entry* entry = (Entry*) dis->itemData;
2388 if (dis->CtlID == IDW_TREE_LEFT)
2389 draw_item(&child->left, dis, entry, -1);
2391 draw_item(&child->right, dis, entry, -1);
2396 InitChildWindow(child);
2400 free_child_window(child);
2401 SetWindowLong(hwnd, GWL_USERDATA, 0);
2408 GetClientRect(hwnd, &rt);
2409 BeginPaint(hwnd, &ps);
2410 rt.left = child->split_pos-SPLIT_WIDTH/2;
2411 rt.right = child->split_pos+SPLIT_WIDTH/2+1;
2412 lastBrush = SelectBrush(ps.hdc, (HBRUSH)GetStockObject(COLOR_SPLITBAR));
2413 Rectangle(ps.hdc, rt.left, rt.top-1, rt.right, rt.bottom+1);
2414 SelectObject(ps.hdc, lastBrush);
2415 #ifdef _NO_EXTENSIONS
2416 rt.top = rt.bottom - GetSystemMetrics(SM_CYHSCROLL);
2417 FillRect(ps.hdc, &rt, GetStockObject(BLACK_BRUSH));
2419 EndPaint(hwnd, &ps);
2423 if (LOWORD(lparam) == HTCLIENT) {
2426 ScreenToClient(hwnd, &pt);
2428 if (pt.x>=child->split_pos-SPLIT_WIDTH/2 && pt.x<child->split_pos+SPLIT_WIDTH/2+1) {
2429 SetCursor(LoadCursor(0, IDC_SIZEWE));
2435 case WM_LBUTTONDOWN: {
2437 int x = LOWORD(lparam);
2439 GetClientRect(hwnd, &rt);
2441 if (x>=child->split_pos-SPLIT_WIDTH/2 && x<child->split_pos+SPLIT_WIDTH/2+1) {
2442 last_split = child->split_pos;
2443 #ifdef _NO_EXTENSIONS
2444 draw_splitbar(hwnd, last_split);
2452 if (GetCapture() == hwnd) {
2453 #ifdef _NO_EXTENSIONS
2455 int x = LOWORD(lparam);
2456 draw_splitbar(hwnd, last_split);
2458 GetClientRect(hwnd, &rt);
2459 child->split_pos = x;
2460 resize_tree(child, rt.right, rt.bottom);
2466 #ifdef _NO_EXTENSIONS
2467 case WM_CAPTURECHANGED:
2468 if (GetCapture()==hwnd && last_split>=0)
2469 draw_splitbar(hwnd, last_split);
2474 if (wparam == VK_ESCAPE)
2475 if (GetCapture() == hwnd) {
2477 #ifdef _NO_EXTENSIONS
2478 draw_splitbar(hwnd, last_split);
2480 child->split_pos = last_split;
2482 GetClientRect(hwnd, &rt);
2483 resize_tree(child, rt.right, rt.bottom);
2486 SetCursor(LoadCursor(0, IDC_ARROW));
2491 if (GetCapture() == hwnd) {
2493 int x = LOWORD(lparam);
2495 #ifdef _NO_EXTENSIONS
2496 HDC hdc = GetDC(hwnd);
2497 GetClientRect(hwnd, &rt);
2499 rt.left = last_split-SPLIT_WIDTH/2;
2500 rt.right = last_split+SPLIT_WIDTH/2+1;
2501 InvertRect(hdc, &rt);
2504 rt.left = x-SPLIT_WIDTH/2;
2505 rt.right = x+SPLIT_WIDTH/2+1;
2506 InvertRect(hdc, &rt);
2508 ReleaseDC(hwnd, hdc);
2510 GetClientRect(hwnd, &rt);
2512 if (x>=0 && x<rt.right) {
2513 child->split_pos = x;
2514 resize_tree(child, rt.right, rt.bottom);
2515 rt.left = x-SPLIT_WIDTH/2;
2516 rt.right = x+SPLIT_WIDTH/2+1;
2517 InvalidateRect(hwnd, &rt, FALSE);
2518 UpdateWindow(child->left.hwnd);
2520 UpdateWindow(child->right.hwnd);
2526 #ifndef _NO_EXTENSIONS
2527 case WM_GETMINMAXINFO:
2528 DefMDIChildProc(hwnd, nmsg, wparam, lparam);
2530 {LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
2532 lpmmi->ptMaxTrackSize.x <<= 1;//2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN
2533 lpmmi->ptMaxTrackSize.y <<= 1;//2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN
2538 SetCurrentDirectory(child->path);
2539 SetFocus(child->focus_pane? child->right.hwnd: child->left.hwnd);
2542 case WM_DISPATCH_COMMAND: {
2543 Pane* pane = GetFocus()==child->left.hwnd? &child->left: &child->right;
2545 switch(LOWORD(wparam)) {
2546 case ID_WINDOW_NEW: {
2547 ChildWnd* new_child = alloc_child_window(child->path);
2549 if (!create_child_window(new_child))
2555 scan_entry(child, pane->cur);
2559 activate_entry(child, pane);
2563 return pane_command(pane, LOWORD(wparam));
2569 Pane* pane = GetFocus()==child->left.hwnd? &child->left: &child->right;
2571 switch(HIWORD(wparam)) {
2572 case LBN_SELCHANGE: {
2573 int idx = ListBox_GetCurSel(pane->hwnd);
2574 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, idx);
2576 if (pane == &child->left)
2577 set_curdir(child, entry);
2583 activate_entry(child, pane);
2588 #ifndef _NO_EXTENSIONS
2590 NMHDR* pnmh = (NMHDR*) lparam;
2591 return pane_notify(pnmh->idFrom==IDW_HEADER_LEFT? &child->left: &child->right, pnmh);}
2595 if (wparam != SIZE_MINIMIZED)
2596 resize_tree(child, LOWORD(lparam), HIWORD(lparam));
2600 return DefMDIChildProc(hwnd, nmsg, wparam, lparam);
2607 LRESULT CALLBACK TreeWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
2609 ChildWnd* child = (ChildWnd*) GetWindowLong(GetParent(hwnd), GWL_USERDATA);
2610 Pane* pane = (Pane*) GetWindowLong(hwnd, GWL_USERDATA);
2614 #ifndef _NO_EXTENSIONS
2621 child->focus_pane = pane==&child->right? 1: 0;
2622 ListBox_SetSel(hwnd, TRUE, 1);
2623 //TODO: check menu items
2627 if (wparam == VK_TAB) {
2628 //TODO: SetFocus(Globals.hdrivebar)
2629 SetFocus(child->focus_pane? child->left.hwnd: child->right.hwnd);
2633 return CallWindowProc(g_orgTreeWndProc, hwnd, nmsg, wparam, lparam);
2637 static void InitInstance(HINSTANCE hinstance)
2639 WNDCLASSEX wcFrame = {
2646 LoadIcon(hinstance, MAKEINTRESOURCE(IDI_WINEFILE)),
2647 LoadCursor(0, IDC_ARROW),
2651 (HICON)LoadImage(hinstance, MAKEINTRESOURCE(IDI_WINEFILE), IMAGE_ICON,
2652 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED)
2655 // register frame window class
2656 ATOM hframeClass = RegisterClassEx(&wcFrame);
2659 WNDCLASS wcChild = {
2660 CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW,
2666 LoadCursor(0, IDC_ARROW),
2672 // register tree windows class
2673 WINE_UNUSED ATOM hChildClass = RegisterClass(&wcChild);
2676 HMENU hMenuFrame = LoadMenu(hinstance, MAKEINTRESOURCE(IDM_WINEFILE));
2677 HMENU hMenuWindow = GetSubMenu(hMenuFrame, GetMenuItemCount(hMenuFrame)-2);
2679 CLIENTCREATESTRUCT ccs = {
2680 hMenuWindow, IDW_FIRST_CHILD
2683 INITCOMMONCONTROLSEX icc = {
2684 sizeof(INITCOMMONCONTROLSEX),
2689 TCHAR path[MAX_PATH];
2693 Globals.hMenuFrame = hMenuFrame;
2694 Globals.hMenuView = GetSubMenu(hMenuFrame, 3);
2695 Globals.hMenuOptions = GetSubMenu(hMenuFrame, 4);
2697 Globals.haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_WINEFILE));
2699 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"));
2703 Globals.hInstance = hinstance;
2705 // create main window
2706 Globals.hMainWnd = CreateWindowEx(0, (LPCTSTR)(int)hframeClass, _T("Wine File"), WS_OVERLAPPEDWINDOW,
2707 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2708 0/*hWndParent*/, Globals.hMenuFrame, hinstance, 0/*lpParam*/);
2711 Globals.hmdiclient = CreateWindowEx(0, _T("MDICLIENT"), NULL,
2712 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
2714 Globals.hMainWnd, 0, hinstance, &ccs);
2717 InitCommonControlsEx(&icc);
2720 TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP};
2724 Globals.hdrivebar = CreateToolbarEx(Globals.hMainWnd, WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
2725 IDW_DRIVEBAR, 2, Globals.hInstance, IDB_DRIVEBAR, &drivebarBtn,
2726 1, 16, 13, 16, 13, sizeof(TBBUTTON));
2727 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_CHECKED);
2729 GetLogicalDriveStrings(BUFFER_LEN, Globals.drives);
2731 drivebarBtn.fsStyle = TBSTYLE_BUTTON;
2733 #ifndef _NO_EXTENSIONS
2735 // insert unix file system button
2736 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)_T("/\0"));
2738 drivebarBtn.idCommand = ID_DRIVE_UNIX_FS;
2739 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
2740 drivebarBtn.iString++;
2743 // register windows drive root strings
2744 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)Globals.drives);
2747 drivebarBtn.idCommand = ID_DRIVE_FIRST;
2749 for(p=Globals.drives; *p; ) {
2750 #ifdef _NO_EXTENSIONS
2751 // insert drive letter
2752 TCHAR b[3] = {tolower(*p)};
2753 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)b);
2755 switch(GetDriveType(p)) {
2756 case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break;
2757 case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break;
2758 case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break;
2759 case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break;
2760 default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
2763 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
2764 drivebarBtn.idCommand++;
2765 drivebarBtn.iString++;
2772 TBBUTTON toolbarBtns[] = {
2773 {0, 0, 0, TBSTYLE_SEP},
2774 {0, ID_WINDOW_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2775 {1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2776 {2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2777 {3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2778 {4, 2/*TODO: ID_...*/, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2779 {5, 2/*TODO: ID_...*/, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2782 Globals.htoolbar = CreateToolbarEx(Globals.hMainWnd, WS_CHILD|WS_VISIBLE,
2783 IDW_TOOLBAR, 2, Globals.hInstance, IDB_TOOLBAR, toolbarBtns,
2784 sizeof(toolbarBtns)/sizeof(TBBUTTON), 16, 15, 16, 15, sizeof(TBBUTTON));
2785 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED);
2788 Globals.hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, Globals.hMainWnd, IDW_STATUSBAR);
2789 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED);
2791 /* CreateStatusWindow does not accept WS_BORDER
2792 Globals.hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0,
2793 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0,
2794 Globals.hMainWnd, (HMENU)IDW_STATUSBAR, hinstance, 0);*/
2796 //TODO: read paths and window placements from registry
2797 GetCurrentDirectory(MAX_PATH, path);
2798 child = alloc_child_window(path);
2800 child->pos.showCmd = SW_SHOWMAXIMIZED;
2801 child->pos.rcNormalPosition.left = 0;
2802 child->pos.rcNormalPosition.top = 0;
2803 child->pos.rcNormalPosition.right = 320;
2804 child->pos.rcNormalPosition.bottom = 280;
2806 if (!create_child_window(child))
2809 SetWindowPlacement(child->hwnd, &child->pos);
2811 Globals.himl = ImageList_LoadBitmap(Globals.hInstance, MAKEINTRESOURCE(IDB_IMAGES), 16, 0, RGB(0,255,0));
2813 Globals.prescan_node = FALSE;
2818 ImageList_Destroy(Globals.himl);
2822 #ifdef _NO_EXTENSIONS
2824 // search for already running win[e]files
2826 static int g_foundPrevInstance = 0;
2828 static BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lparam)
2832 GetClassName(hwnd, cls, 128);
2834 if (!lstrcmp(cls, (LPCTSTR)lparam)) {
2835 g_foundPrevInstance++;
2845 int APIENTRY WinMain(HINSTANCE hinstance,
2846 HINSTANCE previnstance,
2852 #ifdef _NO_EXTENSIONS
2853 // allow only one running instance
2854 EnumWindows(EnumWndProc, (LPARAM)WINEFILEFRAME);
2856 if (g_foundPrevInstance)
2860 InitInstance(hinstance);
2862 if (cmdshow == SW_SHOWNORMAL) {
2863 //TODO: read window placement from registry
2864 cmdshow = SW_MAXIMIZE;
2867 ShowWindow(Globals.hMainWnd, cmdshow);
2868 UpdateWindow(Globals.hMainWnd);
2870 while(GetMessage(&msg, 0, 0, 0)) {
2871 if (!TranslateMDISysAccel(Globals.hmdiclient, &msg) &&
2872 !TranslateAccelerator(Globals.hMainWnd, Globals.haccel, &msg))
2874 TranslateMessage(&msg);
2875 DispatchMessage(&msg);